package com.gotye.particlesystem.gles;

import android.content.Context;
import android.graphics.Color;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;

import com.gotye.particlesystem.R;
import com.gotye.particlesystem.objects.ParticleFirework;
import com.gotye.particlesystem.objects.ParticleShooter;
import com.gotye.particlesystem.objects.ParticleSystem;
import com.gotye.particlesystem.programs.ParticleShaderProgram;
import com.gotye.particlesystem.util.Geometry.Point;
import com.gotye.particlesystem.util.Geometry.Vector;
import com.gotye.particlesystem.util.TextureHelper;

import java.util.List;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * Created by Michael.Ma on 2016/2/1.
 */
public class ParticlesRenderer implements GLSurfaceView.Renderer {
    private Context mContext;

    private long frames = 0L;

    private final float[] projectionMatrix = new float[16];
    private final float[] viewMatrix = new float[16];
    private final float[] viewProjectionMatrix = new float[16];

    private ParticleShaderProgram particleProgram;
    private ParticleSystem particleSystem;
    private ParticleShooter redParticleShooter;
    /*private ParticleShooter greenParticleShooter;
    private ParticleShooter blueParticleShooter;*/
    private List<ParticleFirework> fireList;
    private long globalStartTime;

    private int texture;

    public ParticlesRenderer(Context context) {
        mContext = context;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        particleProgram = new ParticleShaderProgram(mContext);
        particleSystem = new ParticleSystem(5000);
        globalStartTime = System.nanoTime();

        final Vector particleDirection = new Vector(0f, 0.5f, 0f);
        final float angleVarianceInDegrees = 45f;
        final float speedVarience = 1f;

        redParticleShooter = new ParticleShooter(
                new Point(0f, 0f, 0f),
                particleDirection,
                Color.rgb(255, 50, 5),
                angleVarianceInDegrees,
                speedVarience);
        /*greenParticleShooter = new ParticleShooter(
                new Point(0f, 0f, 0f),
                particleDirection,
                Color.rgb(25, 255, 25),
                angleVarianceInDegrees,
                speedVarience);
        blueParticleShooter = new ParticleShooter(
                new Point(1f, 0f, 0f),
                particleDirection,
                Color.rgb(5, 50, 255),
                angleVarianceInDegrees,
                speedVarience);*/

        //fireList = new ArrayList<>();

        texture = TextureHelper.loadTexture(mContext, R.drawable.particle_texture);
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) {
        GLES20.glViewport(0, 0, width, height);

        //MatrixHelper.perspectiveM(projectionMatrix, 45, (float) width / (float) height, 1f, 10f);
        Matrix.setIdentityM(projectionMatrix, 0);
        Matrix.perspectiveM(projectionMatrix, 0, 45, (float) width / (float) height, 1f, 10f);

        Matrix.setIdentityM(viewMatrix, 0);
        Matrix.translateM(viewMatrix, 0, 0f, -1.5f, -5f);
        Matrix.multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
    }

    @Override
    public void onDrawFrame(GL10 gl) {
        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE);
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

        float currentTime = (System.nanoTime() - globalStartTime) / 1000000000f;
        /*if (frames % 100 == 0) {
            final float speedVarience = 1f;

            float[] rotationMatrix = new float[16];
            float[] resultVector = new float[4];
            float[] directionVector = new float[4];

            Matrix.setIdentityM(rotationMatrix, 0);

            Random random = new Random();
            int angleVariance = 10;
            Vector fireDirection = new Vector(0.5f, 1.0f, 0f);
            directionVector[0] = fireDirection.x;
            directionVector[1] = fireDirection.y;
            directionVector[2] = fireDirection.z;

            Matrix.setRotateEulerM(rotationMatrix, 0,
                    (random.nextFloat() - 0.5f) * angleVariance,
                    (random.nextFloat() - 0.5f) * angleVariance,
                    (random.nextFloat() - 0.5f) * angleVariance);

            Matrix.multiplyMV(resultVector, 0,
                    rotationMatrix, 0,
                    directionVector, 0);

            Vector thisDirection = new Vector(
                    resultVector[0],
                    resultVector[1],
                    resultVector[2]
            );

            ParticleFirework firework = new ParticleFirework(new Point(-1f, 0f, 0f),
                    thisDirection,
                    Color.rgb(random.nextInt(255), random.nextInt(255), random.nextInt(255)),
                    speedVarience);
            firework.fire(particleSystem, currentTime);
            fireList.add(firework);
            Log.i("aaa", "firework added");
        }

        Iterator<ParticleFirework> iterator = fireList.iterator();
        while (iterator.hasNext()) {
            ParticleFirework firework = iterator.next();
            firework.update(particleSystem, currentTime);

            if (firework.isExploded()) {
                iterator.remove();
                Log.i("aaa", "firework removed");
            }
        }*/

        redParticleShooter.addParticles(particleSystem, currentTime, 1);
        /*greenParticleShooter.addParticles(particleSystem, currentTime, 5);
        blueParticleShooter.addParticles(particleSystem, currentTime, 5);*/

        particleProgram.useProgram();
        particleProgram.setUniforms(viewProjectionMatrix, currentTime, texture);
        particleSystem.bindData(particleProgram);
        particleSystem.draw();

        frames++;
    }
}
